import { NotFoundException, OnModuleInit } from "@nestjs/common";
import { IPaginationOptions, paginate } from "nestjs-typeorm-paginate";
import { v4 as uuidv4 } from "uuid";
import { SelectQueryBuilder } from "typeorm/query-builder/SelectQueryBuilder";

export abstract class BaseService implements OnModuleInit {
  public model: any;

  public async pageQuery(params: any) {
    const {
      skip,
      take,
      sortBy = "createdAt",
      descending = "DESC",
      ...where
    } = params;
    const newWhere = Object.keys(where).reduce((acc, field) => {
      if (where[field]) {
        acc[field] = where[field];
      }
      return acc;
    }, {});
    const queryBuilder = this.model.createQueryBuilder("t");
    this.lastUpdatePageQuery(queryBuilder);
    queryBuilder.where(newWhere);
    queryBuilder.addOrderBy(`t.${sortBy}`, descending ? "DESC" : "ASC");
    const options: IPaginationOptions = { limit: take, page: skip };
    const pagination = await paginate<any>(queryBuilder, options);
    return pagination;
  }

  /**
   * 通过 ID 删除 Entity
   * @param id
   */
  public async removeById(id: string) {
    const tasks = await this.model.findOne({ id });
    if (!tasks) {
      throw new NotFoundException();
    }

    await this.model.remove([tasks]);
    return true;
  }

  /**
   * 更新数据
   * @param updateEntity
   */
  public async update(updateEntity) {
    const tasks = await this.model.findOne({
      id: updateEntity.id,
    });
    if (!tasks) {
      throw new NotFoundException();
    }

    await this.model.update({ id: updateEntity.id }, updateEntity);
    return true;
  }

  /**
   * 添加数据
   * @param insertEntity
   */
  public async insert(insertEntity) {
    insertEntity.id = uuidv4();
    insertEntity.createdAt = new Date();
    insertEntity.updatedAt = new Date();
    await this.model.insert(insertEntity);
    return true;
  }

  public async batchRemove(ids: string[]) {
    const models = await this.model.findByIds(ids);
    await this.model.remove(models);
    return true;
  }

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  lastUpdatePageQuery(queryBuilder: SelectQueryBuilder<any>) {}
  abstract init();

  onModuleInit() {
    this.init();
  }
}
